<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>.net-.net core中的配置 | haijd</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  <meta name="keywords" content="转载ASP.NET Core" />
  
  
  
  
  <meta name="description" content=".NET-.NET Core中的配置">
<meta name="keywords" content="转载,ASP.NET Core">
<meta property="og:type" content="article">
<meta property="og:title" content=".NET-.NET Core中的配置">
<meta property="og:url" content="http://www.hais2.com/2016/02/20/NET-NET-in-the-Core-Configuration/index.html">
<meta property="og:site_name" content="haijd">
<meta property="og:description" content=".NET-.NET Core中的配置">
<meta property="og:locale" content="default">
<meta property="og:image" content="http://ww3.sinaimg.cn/mw690/c55a7aeejw1f1hcknikwsj20m80njtgs.jpg">
<meta property="og:updated_time" content="2017-08-02T15:22:33.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content=".NET-.NET Core中的配置">
<meta name="twitter:description" content=".NET-.NET Core中的配置">
<meta name="twitter:image" content="http://ww3.sinaimg.cn/mw690/c55a7aeejw1f1hcknikwsj20m80njtgs.jpg">
  
    <link rel="alternate" href="/atom.xml" title="haijd" type="application/atom+xml">
  
  <link rel="icon" href="/css/images/favicon.ico">
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link href="https://fonts.googleapis.com/css?family=Open+Sans|Montserrat:700" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic" rel="stylesheet" type="text/css">
  <link href="//cdn.bootcss.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet">
  <style type="text/css">
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/9749f0/00000000000000000001008f/27/l?subset_id=2&fvd=n5) format("woff2");font-weight:500;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/90cf9f/000000000000000000010091/27/l?subset_id=2&fvd=n7) format("woff2");font-weight:500;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/8a5494/000000000000000000013365/27/l?subset_id=2&fvd=n4) format("woff2");font-weight:lighter;font-style:normal;}
    @font-face{font-family:futura-pt;src:url(https://use.typekit.net/af/d337d8/000000000000000000010095/27/l?subset_id=2&fvd=i4) format("woff2");font-weight:400;font-style:italic;}</style>
    
  <link rel="stylesheet" id="athemes-headings-fonts-css" href="//fonts.googleapis.com/css?family=Yanone+Kaffeesatz%3A200%2C300%2C400%2C700&amp;ver=4.6.1" type="text/css" media="all">
  <link rel="stylesheet" href="/css/style.css">

  <script src="/js/jquery-3.1.1.min.js"></script>

  <!-- Bootstrap core CSS -->
  <link rel="stylesheet" href="/css/bootstrap.css" >
  <link rel="stylesheet" href="/css/hiero.css" >
  <link rel="stylesheet" href="/css/glyphs.css" >
  
    <link rel="stylesheet" href="/css/vdonate.css" >
  

</head>

<script>
var themeMenus = {};

  themeMenus["/"] = "Home"; 

  themeMenus["/archives"] = "Archives"; 

  themeMenus["/categories"] = "Categories"; 

  themeMenus["/tags"] = "Tags"; 

  themeMenus["/about"] = "About"; 

</script>


  <body data-spy="scroll" data-target="#toc" data-offset="50">


  <header id="allheader" class="site-header" role="banner">
  <div class="clearfix container">
      <div class="site-branding">

          <h1 class="site-title">
            
              <a href="/" title="haijd" rel="home"> haijd </a>
            
          </h1>

          
            <div class="site-description">Stay Hungry,Stay Foolish</div>
          
            
          <nav id="main-navigation" class="main-navigation" role="navigation">
            <a class="nav-open">Menu</a>
            <a class="nav-close">Close</a>
            <div class="clearfix sf-menu">

              <ul id="main-nav" class="nmenu sf-js-enabled">
                    
                      <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/">Home</a> </li>
                    
                      <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/archives">Archives</a> </li>
                    
                      <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/categories">Categories</a> </li>
                    
                      <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/tags">Tags</a> </li>
                    
                      <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-1663"> <a class="" href="/about">About</a> </li>
                    
              </ul>
            </div>
          </nav>


      </div>
  </div>
</header>




  <div id="container">
    <div id="wrap">
            
      <div id="content" class="outer">
        
          <section id="main" style="float:none;"><article id="post-NET-NET-in-the-Core-Configuration" style="width: 66%; float:left;" class="article article-type-post" itemscope itemprop="blogPost" >
  <div id="articleInner" class="clearfix post-1016 post type-post status-publish format-standard has-post-thumbnail hentry category-template-2 category-uncategorized tag-codex tag-edge-case tag-featured-image tag-image tag-template">
    
    
      <header class="article-header">
        
  
    <h1 class="thumb" class="article-title" itemprop="name">
      .NET-.NET Core中的配置
    </h1>
  

      </header>
    
    <div class="article-meta">
      
	Posted on <a href="/2016/02/20/NET-NET-in-the-Core-Configuration/" class="article-date">
	  <time datetime="2016-02-20T05:31:43.000Z" itemprop="datePublished">February 20, 2016</time>
	</a>

      
	<span id="busuanzi_container_page_pv">
	  本文总阅读量<span id="busuanzi_value_page_pv"></span>次
	</span>

    </div>
    <div class="article-entry" itemprop="articleBody">
      
        <blockquote>
<p>就在截稿时间之前，Microsoft 宣布了更改 ASP.NET 5 和相关堆叠的名称。ASP.NET 5 已更名为 ASP.NET Core 1.0。Entity Framework (EF) 7 已更名为 Entity Framework (EF) Core 1.0。虽然 ASP.NET 5 和 EF7 程序包以及命名空间将会发生变化，但新的命名法不会对本文中的课程造成任何影响。</p>
</blockquote>
<p>使用 ASP.NET 5 的同仁们自然都会注意到此平台中新增了配置支持，可用于 NuGet 包的 Microsoft.Extensions.Configuration 集合。新的配置支持名称/值对列表（可分入多层层次结构）。例如，您可以将一个设置存储在 SampleApp:Users:InigoMontoya:MaximizeMainWindow 中，将另一个设置存储在 SampleApp:AllUsers:Default:MaximizeMainWindow 中。存储的所有值都会映射到字符串，您可以借助内置的绑定支持，将设置反序列化为自定义 POCO 对象。已经熟悉新配置 API 的同仁们可能最初是在 ASP.NET 5 注意到的。不过，此 API 绝不仅限于 ASP.NET。实际上，本文中的所有列表都是使用 Microsoft .NET Framework 4.5.1（同时引用 ASP.NET 5 RC1 中的 Microsoft.Extensions.Configuration 包）在 Visual Studio 2015 单元测试项目中创建（有关源代码，请访问 <a href="http://github.com/IntelliTect/Articles" target="_blank" rel="noopener">gitHub.com/IntelliTect/Articles</a>）。<br><a id="more"></a><br>配置 API 支持内存中 .NET 对象、INI 文件、JSON 文件、XML 文件、命令行自变量、环境变量、加密的用户存储的配置提供程序，以及您创建的所有自定义提供程序。如果您希望对自己的配置利用 JSON 文件，只需添加 Microsoft.Extensions.Configuration.Json NuGet 包。然后，如果您想允许命令行提供配置信息，只需添加 Microsoft.Extensions.Configuration.CommandLine NuGet 包即可（可以在其他配置引用的基础上另外添加，也可以替代其他配置引用添加）。如果您对内置的所有配置提供程序都不满意，也可以创建您自己的提供程序，方法为实现 Microsoft.Extensions.Configuration.Abstractions 中的接口。</p>
<h3 id="检索配置设置"><a href="#检索配置设置" class="headerlink" title="检索配置设置"></a>检索配置设置</h3><p>请查看图 1，自行熟悉如何检索配置设置。<br>图 1：使用 InMemoryConfigurationProvider 和 ConfigurationBinder 扩展方法的基本配置:<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">Program</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">public</span> <span class="keyword">string</span> DefaultConnectionString &#123; <span class="keyword">get</span>; &#125; =</span><br><span class="line">    <span class="string">@"Server=(localdb)\\mssqllocaldb;Database=SampleData-0B3B0919-C8B3-481C-9833-</span></span><br><span class="line"><span class="string">    36C21776A565;Trusted_Connection=True;MultipleActiveResultSets=true"</span>;</span><br><span class="line">  <span class="keyword">static</span> IReadOnlyDictionary&lt;<span class="keyword">string</span>, <span class="keyword">string</span>&gt; DefaultConfigurationStrings&#123;<span class="keyword">get</span>;&#125; =</span><br><span class="line">    <span class="keyword">new</span> Dictionary&lt;<span class="keyword">string</span>, <span class="keyword">string</span>&gt;()</span><br><span class="line">    &#123;</span><br><span class="line">      [<span class="meta"><span class="meta-string">"Profile:UserName"</span></span>] = Environment.UserName,</span><br><span class="line">      [<span class="meta">$<span class="meta-string">"AppConfiguration:ConnectionString"</span></span>] = DefaultConnectionString,</span><br><span class="line">      [<span class="meta">$<span class="meta-string">"AppConfiguration:MainWindow:Height"</span></span>] = <span class="string">"400"</span>,</span><br><span class="line">      [<span class="meta">$<span class="meta-string">"AppConfiguration:MainWindow:Width"</span></span>] = <span class="string">"600"</span>,</span><br><span class="line">      [<span class="meta">$<span class="meta-string">"AppConfiguration:MainWindow:Top"</span></span>] = <span class="string">"0"</span>,</span><br><span class="line">      [<span class="meta">$<span class="meta-string">"AppConfiguration:MainWindow:Left"</span></span>] = <span class="string">"0"</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">public</span> IConfiguration Configuration &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>(<span class="params"><span class="keyword">string</span>[] args = <span class="literal">null</span></span>)</span></span><br><span class="line"><span class="function">  </span>&#123;</span><br><span class="line">    ConfigurationBuilder configurationBuilder =</span><br><span class="line">      <span class="keyword">new</span> ConfigurationBuilder();</span><br><span class="line">      <span class="comment">// Add defaultConfigurationStrings</span></span><br><span class="line">      configurationBuilder.AddInMemoryCollection(</span><br><span class="line">        DefaultConfigurationStrings);</span><br><span class="line">      Configuration = configurationBuilder.Build();</span><br><span class="line">      Console.WriteLine(<span class="string">$"Hello <span class="subst">&#123;Configuration[<span class="string">"Profile:UserName"</span>]&#125;</span>"</span>);</span><br><span class="line">      ConsoleWindow consoleWindow =</span><br><span class="line">        Configuration.Get&lt;ConsoleWindow&gt;(<span class="string">"AppConfiguration:MainWindow"</span>);</span><br><span class="line">      ConsoleWindow.SetConsoleWindow(consoleWindow);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>若要轻松访问配置，请先从 ConfigurationBuilder 实例入手，这是 Microsoft.Extensions.Configuration NuGet 包中的类。借助 ConfigurationBuilder 实例，您可以使用 IConfigurationBuilder 扩展方法（如 AddInMemoryCollection）直接添加提供程序，如图 1 所示。此方法提取配置名称/值对的 Dictionary&lt;string,string&gt; 实例，以便在将其添加到 ConifigurationBuilder 实例之前初始化配置提供程序。在“已配置”配置生成器后，您可以调用其 Build 方法来检索配置。</p>
<p>如前所述，配置就是名称/值对的分层列表，其中节点是由冒号分隔。因此，若要检索特定值，您只需使用相应项目的密钥访问配置索引器即可：<br><figure class="highlight less"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">Console</span><span class="selector-class">.WriteLine</span>($<span class="string">"Hello &#123;Configuration["</span><span class="attribute">Profile</span>:UserName<span class="string">"]&#125;"</span>);</span><br></pre></td></tr></table></figure></p>
<p>不过，访问值并不仅限于检索字符串。例如，您可以通过 ConfigurationBinder 的 Get<t> 扩展方法检索值。比如，若要检索主要窗口屏幕缓冲区大小，您可以使用：<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">Configuration</span><span class="selector-class">.Get</span>&lt;<span class="selector-tag">int</span>&gt;("<span class="selector-tag">AppConfiguration</span><span class="selector-pseudo">:MainWindow</span><span class="selector-pseudo">:ScreenBufferSize"</span>, 80);</span><br></pre></td></tr></table></figure></t></p>
<p>这种绑定支持需要引用 Microsoft.Extensions.Configuration.Binder NuGet 包。</p>
<p>请注意，密钥后面有一个可选自变量，您可以用来指定在密钥不存在时返回的默认值（如果没有默认值，那么会返回所分配的 default(T)，而不是像您所预料的那样引发异常）。</p>
<p>配置值并不仅限于标量。您可以检索 POCO 对象或甚至整个对象图。为了检索其成员映射到 AppConfiguration:MainWindow 配置部分的 ConsoleWindow 实例，图 1 使用：<br><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ConsoleWindow consoleWindow =</span><br><span class="line">  Configuration.Get<span class="params">&lt;ConsoleWindow&gt;</span>(<span class="string">"AppConfiguration:MainWindow"</span>)</span><br></pre></td></tr></table></figure></p>
<p>或者，您可以定义配置图表（如 AppConfiguration），如图 2 所示。<br>图 2：示例配置对象图:<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title">AppConfiguration</span></span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> ProfileConfiguration Profile &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">   <span class="keyword">public</span> <span class="keyword">string</span> ConnectionString &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">  <span class="keyword">public</span> WindowConfiguration MainWindow &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">WindowConfiguration</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> Height &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> Width &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> Left &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">int</span> Top &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">ProfileConfiguration</span></span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">string</span> UserName &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">  AppConfiguration appConfiguration =</span><br><span class="line">    Program.Configuration.Get&lt;AppConfiguration&gt;(</span><br><span class="line">      <span class="keyword">nameof</span>(AppConfiguration));</span><br><span class="line">  <span class="comment">// Requires referencing System.Diagnostics.TraceSource in Corefx</span></span><br><span class="line">  System.Diagnostics.Trace.Assert(</span><br><span class="line">    <span class="number">600</span> == appConfiguration.MainWindow.Width);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>有了此类对象图，您可以使用强类型对象层次结构（随后可使用此层次结构一次性检索所有设置）定义所有或部分配置。</p>
<h3 id="多个配置提供程序"><a href="#多个配置提供程序" class="headerlink" title="多个配置提供程序"></a>多个配置提供程序</h3><p>InMemoryConfigurationProvider 可有效用于存储默认值或可能的已计算值。不过，如果您仅使用此提供程序，那么在使用 ConfigurationBuilder 注册配置之前，您需要检索配置并将配置加载到 Dictionary&lt;string,string&gt; 中，负担很重。幸运的是，您还可以使用更多内置配置提供程序，包括三个基于文件的提供程序（XmlConfigurationProvider、IniConfigurationProvider 和 JsonConfigurationProvider）、一个环境变量提供程序 (EnvironmentVariableConfigurationProvider)、一个命令行自变量提供程序 (CommandLineConfigurationProvider)。此外，您还可以根据自己的应用程序逻辑来混合使用这些提供程序。例如，您可以按以下升序优先顺序来指定配置设置：<br>　　● InMemoryConfigurationProvider<br>　　● 适用于 Config.json 的 JsonFileConfigurationProvider<br>　　● 适用于 Config.Production.json 的 JsonFileConfigurationProvider<br>　　● EnvironmentVariableConfigurationProvider<br>　　● CommandLineConfigurationProvider</p>
<p>换言之，默认配置值可能存储在代码中。接下来，Config.Production.json 前面的 config.json 文件可能会替代 InMemory 指定的值，稍后 JSON 等提供程序将优先处理所有重叠值。然后，在部署时，您可能会在环境变量中存储自定义配置值。例如，您可能会从 Windows 环境变量中检索环境设置，然后访问环境变量确定的特定文件（可能是 Config.Test.Json），而不是对 Config.Production.json 进行硬编码（“环境设置”一词有多义性：与生产、测试、预生产或开发、%USERNAME% 或 %USERDOMAIN% 等 Windows 环境变量相关）。 最后，您通过命令行指定（或替代）之前提供的所有设置（例如，可能一次性更改为启用日志记录）。</p>
<p>若要指定各个提供程序，请将它们添加到配置生成器中（通过扩展方法 AddX Fluent API），如图 3 所示：<br>图 3：添加多个配置提供程序（最后指定的提供程序优先）：<br><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="built_in">void</span> Main(<span class="built_in">string</span>[] args = <span class="literal">null</span>)</span><br><span class="line">&#123;</span><br><span class="line">  ConfigurationBuilder configurationBuilder =</span><br><span class="line">    <span class="keyword">new</span> ConfigurationBuilder();</span><br><span class="line">  configurationBuilder</span><br><span class="line">    .AddInMemoryCollection(DefaultConfigurationStrings)</span><br><span class="line">    .AddJsonFile(<span class="string">"Config.json"</span>,</span><br><span class="line">      <span class="literal">true</span>) <span class="comment">// Bool indicates file is optional</span></span><br><span class="line">    <span class="comment">// "EssentialDotNetConfiguartion" is an optional prefix for all</span></span><br><span class="line">    <span class="comment">// environment configuration keys, but once used,</span></span><br><span class="line">    <span class="comment">// only environment variables with that prefix will be found        </span></span><br><span class="line">    .AddEnvironmentVariables(<span class="string">"EssentialDotNetConfiguration"</span>)</span><br><span class="line">    .AddCommandLine(</span><br><span class="line">      args, GetSwitchMappings(DefaultConfigurationStrings));</span><br><span class="line">  Console.WriteLine($<span class="string">"Hello &#123;Configuration["</span>Profile:UserName<span class="string">"]&#125;"</span>);</span><br><span class="line">  AppConfiguration appConfiguration =</span><br><span class="line">    Configuration.Get&lt;AppConfiguration&gt;(nameof(AppConfiguration));</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">static</span> <span class="keyword">public</span> Dictionary&lt;<span class="built_in">string</span>,<span class="built_in">string</span>&gt; GetSwitchMappings(</span><br><span class="line">  IReadOnlyDictionary&lt;<span class="built_in">string</span>, <span class="built_in">string</span>&gt; configurationStrings)</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">return</span> configurationStrings.Select(<span class="function"><span class="params">item</span> =&gt;</span></span><br><span class="line">    <span class="keyword">new</span> KeyValuePair&lt;<span class="built_in">string</span>, <span class="built_in">string</span>&gt;(</span><br><span class="line">      <span class="string">"-"</span> + item.Key.Substring(item.Key.LastIndexOf(<span class="string">':'</span>)+<span class="number">1</span>),</span><br><span class="line">      item.Key))</span><br><span class="line">      .ToDictionary(</span><br><span class="line">        item =&gt; item.Key, <span class="function"><span class="params">item</span>=&gt;</span>item.Value);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>对于 JsonConfigurationProvider，您可以将文件设为必有或可选；因此，需要在 AddJsonFile 上添加其他可选参数。如果您没有提供任何参数，那么文件为必有。如果找不到文件，则会触发 System.IO.FileNotFoundException。鉴于 JSON 的分层性质，配置非常适合配置 API（见图 4）。<br>图 4：JsonConfigurationProvider 的 JSON 配置数据:<br><figure class="highlight clojure"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="string">"AppConfiguration"</span>: &#123;</span><br><span class="line">    <span class="string">"MainWindow"</span>: &#123;</span><br><span class="line">      <span class="string">"Height"</span>: <span class="string">"400"</span>,</span><br><span class="line">      <span class="string">"Width"</span>: <span class="string">"600"</span>,</span><br><span class="line">      <span class="string">"Top"</span>: <span class="string">"0"</span>,</span><br><span class="line">      <span class="string">"Left"</span>: <span class="string">"0"</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">"ConnectionString"</span>:</span><br><span class="line">      <span class="string">"Server=(localdb)\\\\mssqllocaldb;Database=Database-0B3B0919-C8B3-481C-9833-</span></span><br><span class="line"><span class="string">      36C21776A565;Trusted_Connection=True;MultipleActiveResultSets=true"</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>CommandLineConfigurationProvider 要求您在使用配置生成器注册它时指定自变量。通过名称/值对的字符串数组指定自变量，每一对均采用 <code>/&lt;name&gt;=&lt;value&gt;</code> 格式，其中必须有等号。前导斜线也是必须有的，但函数 AddCommandLine(string[] args, Dictionary&lt;string,string&gt; switchMappings) 的第二个参数允许您提供前缀必须为 - 或 – 的别名。例如，值字典将允许将命令行“program.exe -LogFile=”c:\programdata\Application Data\Program.txt”加载到 AppConfiguration:LogFile configuration 元素中：<br><figure class="highlight cs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[<span class="meta"><span class="meta-string">"-DBConnectionString"</span></span>]=<span class="string">"AppConfiguration:ConnectionString"</span>,</span><br><span class="line">  [<span class="meta"><span class="meta-string">"-LogFile"</span></span>]=<span class="string">"AppConfiguration:LogFile"</span></span><br></pre></td></tr></table></figure></p>
<p>在完成基本配置之前，您还需要另外注意以下几点：<br>　　● CommandLineConfigurationProvider 具有多项并非 IntelliSense 原生的特性，您需要多加注意：<br>　　　　○ CommandLineConfigurationProvider 的 switchMappings 只允许使用开关前缀 - 或 –。即使是斜线 (/)，也不允许用作开关参数。这样可避免您通过开关映射提供斜线开关的别名。<br>　　　　○ CommandLineConfigurationProvider 不允许使用基于开关的命令行自变量（即，不包含赋值的自变量）。例如，不允许指定密钥“/Maximize”。<br>　　　　○ 虽然您可以向新的 CommandLineConfigurationProvider 实例传递 Main 的自变量，但如果没有先删除进程名称，则无法传递 Environment.GetCommandLineArgs。（请注意，在附加调试器后，Environment.GetCommandLineArgs 的行为不同。具体而言，如果没有附加调试器，那么含空格的可执行文件名会被分成各个自变量。请参阅 itl.ty\GetCommandLineGotchas。）<br>　　　　○ 如果您指定的命令行开关前缀 - 或 – 没有对应的开关映射，则会引发异常。<br>　　● 虽然配置可以更新 (<code>Configuration[&quot;Profile:UserName&quot;]=&quot;Inigo Montoya&quot;</code>)，但更新后的值不会继续保留回原始存储。例如，当您分配 JSON 提供程序配置值时，就不会更新 JSON 文件。同样，环境变量也不会在其配置项分配时进行更新。<br>　　● EnvironmentVariableConfigurationProvider 可以视情况允许您指定密钥前缀。在这种情况下，它只会加载具有指定前缀的环境变量。这样一来，您可以自动将配置项限定为环境变量“section”内的配置项，或从更广泛的角度来讲与您的应用程序相关的配置项。<br>　　● 支持包含冒号分隔符的环境变量。例如，允许在命令行上分配 SET AppConfiguration:ConnectionString=Console。<br>　　● 所有配置密钥（名称）均不区分大小写。<br>　　● 每个提供程序均位于各自的 NuGet 包内，其中 NuGet 包名称与提供程序相对应： Microsoft.Extensions.Configuration.CommandLine、Microsoft.Extensions.Configuration.EnvironmentVariables、Microsoft.Extensions.Configuration.Ini、Microsoft.Extensions.Configuration.Json 和 Microsoft.Extensions.Configuration.Xml。</p>
<h3 id="了解面向对象的结构"><a href="#了解面向对象的结构" class="headerlink" title="了解面向对象的结构"></a>了解面向对象的结构</h3><p>配置 API 的模块性和面向对象的结构均已经过认真研究，提供可检测到且可轻松扩展的模块类和接口方便您使用（见图 5）。<br>图 5：配置提供程序类模型 ：<br><img src="http://ww3.sinaimg.cn/mw690/c55a7aeejw1f1hcknikwsj20m80njtgs.jpg" alt=""><br>每种类型的配置机制均有对应的配置提供程序类来实现 IConfigurationProvider。对于大多数的内置提供程序实现，实现的快速启动方式是从 ConfigurationBuilder 派生，而不是对所有的接口方法使用自定义实现。无法直接引用图 1 中的任何提供程序，这一点或许有些令人惊讶。这是因为每个提供程序的 NuGet 包内有静态扩展类和 IConfigurationBuilder 扩展方法，不用您手动实例化每个提供程序并使用 ConfigurationBuilder 类的 Add 方法注册提供程序（扩展类的名称通常是由后缀 ConfigurationExtensions 确定）。 借助扩展类，您可以开始直接从 ConfigurationBuilder（可实现 IConfigurationBuilder）访问配置数据，并直接调用与您的提供程序相关联的扩展方法。例如，JasonConfigurationExtensions 类向 IConfigurationBuilder 添加 AddJsonFile 扩展方法，以便您可以通过调用 Configuration­Builder.AddJsonFile(fileName, optional).Build(); 来添加 JSON 配置。<br>大部分情况下，只要拥有配置，您就拥有了开始检索值所需的一切。</p>
<p>IConfiguration 包含字符串索引器，允许您使用密钥检索任意特定的配置值，从而访问要查找的元素。您可以使用 GetSection 或 GetChildren 方法检索整个设置集（称为 section），具体取决于您是否想深入到层次结构中的另一层级。请注意，配置元素部分允许您检索以下内容：<br>　　● 密钥：名称的最后一个元素。<br>　　● 路径：从根指向当前位置的完整名称。<br>　　● 值：存储在配置设置中的配置值。<br>　　● 对象形式的值：通过 ConfigurationBinder，您可以检索与要访问的配置部分（可能包括其子部分）相对应的 POCO 对象。这就是图 3 中的示例 Configuration.Get<appconfiguration>(nameof(App­Configuration)) 的工作原理。<br>　　● IConfigurationRoot 包含 Reload 函数，可允许您重新加载值，以便更新配置。ConfigurationRoot（可实现 IConfigurationRoot）包含 GetReloadToken 方法，以便您可以针对在重新加载发生（以及值可能发生变化）时发出的通知进行注册。</appconfiguration></p>
<h3 id="加密的设置"><a href="#加密的设置" class="headerlink" title="加密的设置"></a>加密的设置</h3><p>有时，您需要检索加密的设置，而不是存储在开放文本中的设置。例如，当您要存储 OAuth 应用程序密钥或令牌时，或当您要存储数据库连接字符串的凭据时，这一点就非常重要。幸运的是，Microsoft.Extensions.Configuration 系统内置对读取加密值的支持。若要访问安全存储，您需要添加对 Microsoft.Extensions.Configuration.User­Secrets NuGet 包的引用。添加后，您将获得新的 IConfigurationBuilder.AddUserSecrets 扩展方法，用于提取称为“userSecretsId”的配置项字符串自变量（存储在您的 project.json 文件中）。正如您所期望的那样，在向配置生成器添加 UserSecrets 配置后，您便可以开始检索加密值，而这只有与设置相关联的用户才能访问。</p>
<p>显然，如果您无法设定设置，那么检索设置就有点多余。为此，请使用 user-secret.cmd 工具，如下所示：<br><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">user-secret <span class="built_in">set</span> <span class="variable">&lt;secretName&gt;</span> <span class="variable">&lt;value&gt;</span> [--project <span class="variable">&lt;projectPath&gt;</span>]</span><br></pre></td></tr></table></figure></p>
<p>借助 –project 选项，您可以将设置与 project.json 文件（默认由 ASP.NET 5 新项目向导创建）中存储的 userSecretsId 值相关联。如果您没有 user-secret 工具，则需要通过开发者命令提示符并使用 DNX 实用工具（当前为 dnu.exe）来添加。</p>
<p>若要详细了解如何使用用户机密配置选项，请参阅 Rick Anderson 和 David Roth 撰写的“应用程序机密的安全存储”一文 (<a href="http://bit.ly/1mmnG0L" target="_blank" rel="noopener">bit.ly/1mmnG0L</a>)。</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>接触 .NET 已有一段时间的同仁们可能已对通过 System.Configuration 提供的内置配置支持感到非常失望。如果您之前使用的是经典 ASP.NET，则情况更是如此。在经典 ASP.NET 中，配置仅限于 Web.Config 或 App.config 文件，且只能通过访问其中的 AppSettings 节点。幸运的是，全新的开放源代码 Microsoft.Extensions.Configuration API 在最初版本的基础上实现了很大飞跃，添加了各种新的配置提供程序，以及可方便您连接任意所需的自定义提供程序的可轻松扩展的系统。对于那些仍在使用旧版 ASP.NET 5（苦苦挣扎？）的同仁们，虽然旧版 System.Configuration API 仍可运行，但您可以慢慢开始迁移到（甚至并行运行）新版 API，只需引用新包即可。此外，您还可以在控制台等 Windows 客户端项目和 Windows Presentation Foundation 应用程序中使用 NuGet 包。因此，当您下次需要访问配置数据时，就没有理由不使用 Microsoft.Extensions.Configuration API 了。</p>
<p>原文来自<a href="https://msdn.microsoft.com/zh-cn/magazine/mt632279" target="_blank" rel="noopener">MSND订阅杂志</a><br>作者：<strong>Mark Michaelis</strong></p>

      
    </div>
    <footer class="entry-meta entry-footer">
      
	<span class="ico-folder"></span>
    <a class="article-category-link" href="/categories/ASP-NET/">ASP.NET</a>

      
  <span class="ico-tags"></span>
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ASP-NET-Core/">ASP.NET Core</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/转载/">转载</a></li></ul>

      
        <div id="donation_div"></div>

<script src="/js/vdonate.js"></script>
<script>
var a = new Donate({
  title: '如果觉得我的文章对您有用，请随意打赏。您的支持将鼓励我继续创作!', // 可选参数，打赏标题
  btnText: 'Donate', // 可选参数，打赏按钮文字
  el: document.getElementById('donation_div'),
  wechatImage: '/css/images/wechatPay.png',
  alipayImage: '/css/images/alipay.jpg'
});
</script>
      

      
        
	<section id="comments" class="comment">
	  <div id="disqus_thread">
	  <noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
	  </div>
	</section>

	<script type="text/javascript">
	var disqus_shortname = 'haijdblog';
	(function(){
	  var dsq = document.createElement('script');
	  dsq.type = 'text/javascript';
	  dsq.async = true;
	  dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
	  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
	}());
	(function(){
	  var dsq = document.createElement('script');
	  dsq.type = 'text/javascript';
	  dsq.async = true;
	  dsq.src = '//' + disqus_shortname + '.disqus.com/count.js';
	  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
	}());
	</script>


      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/2016/02/24/Understanding-RESTful/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          理解RESTful
        
      </div>
    </a>
  
  
    <a href="/2016/02/16/Data-ASP-NET5-EF6-reconstruction-projects-and-dependency-injection/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">数据点-重构ASP.NET5/EF6项目和依赖关系注入</div>
    </a>
  
</nav>

  
</article>

<!-- Table of Contents -->

  <aside id="sidebar">
    <div id="toc" class="toc-article">
    <strong class="toc-title">Contents</strong>
    
      <ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#检索配置设置"><span class="nav-number">1.</span> <span class="nav-text">检索配置设置</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#多个配置提供程序"><span class="nav-number">2.</span> <span class="nav-text">多个配置提供程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#了解面向对象的结构"><span class="nav-number">3.</span> <span class="nav-text">了解面向对象的结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#加密的设置"><span class="nav-number">4.</span> <span class="nav-text">加密的设置</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#总结"><span class="nav-number">5.</span> <span class="nav-text">总结</span></a></li></ol>
    
    </div>
  </aside>
</section>
        
      </div>
      <footer id="footer" class="site-footer">
  

  <div class="clearfix container">
      <div class="site-info">
	      &copy; 2018 haijd All Rights Reserved.
          
            <span id="busuanzi_container_site_uv">
              本站访客数<span id="busuanzi_value_site_uv"></span>人次  
              本站总访问量<span id="busuanzi_value_site_pv"></span>次
            </span>
          
      </div>
      <div class="site-credit">
        Theme by <a href="https://github.com/iTimeTraveler/hexo-theme-hiero" target="_blank">hiero</a>
      </div>
  </div>
</footer>


<!-- min height -->

<script>
    var contentdiv = document.getElementById("content");

    contentdiv.style.minHeight = document.body.offsetHeight - document.getElementById("allheader").offsetHeight - document.getElementById("footer").offsetHeight + "px";
</script>
    </div>
    <!-- <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
    <a href="/categories" class="mobile-nav-link">Categories</a>
  
    <a href="/tags" class="mobile-nav-link">Tags</a>
  
    <a href="/about" class="mobile-nav-link">About</a>
  
</nav> -->
    

<!-- mathjax config similar to math.stackexchange -->

<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [ ['$','$'], ["\\(","\\)"] ],
      processEscapes: true
    }
  });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Config({
      tex2jax: {
        skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
      }
    });
</script>

<script type="text/x-mathjax-config">
    MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for(i=0; i < all.length; i += 1) {
            all[i].SourceElement().parentNode.className += ' has-jax';
        }
    });
</script>

<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/scripts.js"></script>
<script src="/js/bootstrap.js"></script>
<script src="/js/main.js"></script>








	<script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js">
	</script>






  </div>

  <a id="rocket" href="#top" class=""></a>
  <script type="text/javascript" src="/js/totop.js" async=""></script>
</body>
</html>
